from django.utils.deprecation import MiddlewareMixin
from django.http import JsonResponse
import jwt
import datetime
import time
import uuid
from .models import Users


def token_decrypt(token):
    salt = '*&&%^%#$$'
    try:
        data = jwt.decode(token, salt, algorithms=[
            'HS256'], detached_payload=False)
        return data, True
    except jwt.ExpiredSignatureError:
        return {"msg": '登录已过期'}, False
    except jwt.DecodeError:
        return {"msg": '用户信息认证失败'}, False
    except jwt.InvalidTokenError:
        return {"msg": '无效的登录信息'}, False


def token_encryption(user, duration):  # 需要两个参数，用户登录信息和token保存时长（第二个参数表示天数）
    salt = "*&&%^%#$$"
    payload = {
        "user_account": user["user_account"],
        "key": user["key"],
        "exp": datetime.datetime.utcnow() + datetime.timedelta(days=duration),  # exp 配置token有效时长天数
    }
    token = jwt.encode(payload=payload, key=salt, algorithm="HS256")
    return token


class MyMiddle(MiddlewareMixin):
    @staticmethod
    def process_request(request):
        try:
            request_url = request.path
            # 拦截白名单
            white_list = ['/users/code', '/users/create', '/users/login', '/users/check']
            isAdmin = request_url.find("admin") >= 0 or request_url.find("/static") >= 0  # admin后台和静态文件关闭拦截
            if request_url in white_list or isAdmin:
                return None
            token = request.META.get('HTTP_TOKEN', None)
            if token:
                data, isUse = token_decrypt(token)  # 将token换成对象，查看是否还在使用期限内
                if isUse:  # token未失效时的情况，继续判断一次用户名和随机码是否正确
                    db_data = Users.objects.filter(user_account=data['user_account']).values().first()
                    if data['key'] == db_data['key']:
                        if time.time() > data['exp']:  # 此次判断是为了防止出现bug
                            return JsonResponse({'code': 403, "message": '登录信息已过期'})
                        # 如果3天不登录，直接走登录信息过期的流程，这里固定的是三天的过期时间，乘以1表示两天续签，乘以2表示隔天续签，
                        # 注意如果乘以3表示当天续签会导致页面重复刷新重复请求，因此这里的数字不能大于等于3，大于等于3会导致系统一直重复刷新
                        if time.time() > data['exp'] - (3600 * 24 * 1):  # 过期的前一天开始续签token
                            uid = str(uuid.uuid4())
                            uu_code = ''.join(uid.split("-"))
                            user = {'user_account': data['user_account'], 'key': uu_code}
                            token_txt = token_encryption(user, 3)
                            return JsonResponse({'code': 401, "data": token_txt})  # 401 是特殊字段，只能用于刷新token
                    else:
                        return JsonResponse(
                            {'code': 403, "message": '您的账户已在别处登录，如不是本人操作，建议您及时修改密码'})
                else:
                    return JsonResponse({'code': 403, "message": data['msg']})
            else:
                return JsonResponse({'code': 403, "message": "登录信息不存在"})
        except Exception as e:
            return JsonResponse({'code': 403, "message": '服务器错误：' + str(e)})

    # def process_response(self, request, response):
    #     return response
    #
    # # def process_view(self, request, callback, callback_args, callback_kwargs):
    # #     return None
